/**
  ******************************************************************************
  * @file    al_serial.c
  * @author  exatron
  * @version V1.0.0
  * @date    segunda, 22 de dezembro de 2014
  * @brief   Funções de manipulação da porta serial.
  ******************************************************************************
  * @attention
  *
  *
  ******************************************************************************
  */

/** @addtogroup Serial
  * @{
  */

/* Includes ------------------------------------------------------------------*/
#include <common.h>

/* Private variables ---------------------------------------------------------*/
int 			ttyS0_fd;					/*!< Control file descriptor */
int 			ttyS1_fd;					/*!< Data file descriptor */
static struct 	termios tio;				/*!< Termios struct */
int				serial0_timeout = 0;		/*!< Contador timeout serial 0 */
int				serial1_timeout = 0;		/*!< Contador timeout serial 1 */
int				serial_timeout = 0;			/*!< Conf do timeout serial */

/* Private function prototypes -----------------------------------------------*/
int aux_USART0_open();
int aux_USART1_open();

/* Private functions ---------------------------------------------------------*/

/** @defgroup Serial_Functions
  * @{
  */

/**
  * @brief  Configura portas seriais e threads.
  * @param  Nenhum
  * @retval Nenhum
  */
void aux_USART_open()
{
	serial_timeout = aux_CFG_GetTimeOutUSART();
	aux_USART0_open();
	aux_USART1_open();
}

/**
  * @brief  Abre a porta serial ttyS0 Controle.
  * @param  Nenhum
  * @retval Nenhum
  */
int aux_USART0_open()
{
	#ifdef DEBUG_ON_PC
    memset(&tio,0,sizeof(tio));
    tio.c_iflag=0;
    tio.c_oflag=0;
    tio.c_cflag=0;
    tio.c_lflag=0;
    tio.c_cc[VMIN]=0;
    tio.c_cc[VTIME]=0;
    tcsetattr(STDOUT_FILENO,TCSANOW,&tio);
    tcsetattr(STDOUT_FILENO,TCSAFLUSH,&tio);
	#else
    bzero(&tio,sizeof(tio));
    tio.c_iflag = 0;
    tio.c_oflag = 0;
    tio.c_cflag = CS8|CREAD|CLOCAL; // 8n1
    tio.c_lflag = 0;
    tio.c_cc[VMIN] = 0;
    tio.c_cc[VTIME] = (serial_timeout*10);

    ttyS0_fd = open(USART_DEV_CONTROL, O_RDWR | O_NONBLOCK);
    if(ttyS0_fd == -1)
    	return EXIT_FAILURE;
    cfsetospeed(&tio, aux_CFG_GetBaudRate(SERIAL_CONTROL));
    cfsetispeed(&tio, aux_CFG_GetBaudRate(SERIAL_CONTROL));
    tcsetattr(ttyS0_fd,TCSANOW,&tio);
    tcflush(ttyS0_fd, TCIOFLUSH);
	#endif

    return EXIT_SUCCESS;
}

/**
  * @brief  Abre a porta serial ttyS1 Dados.
  * @param  Nenhum
  * @retval Nenhum
  */
int aux_USART1_open()
{
	#ifndef DEBUG_ON_PC
    bzero(&tio,sizeof(tio));
    tio.c_iflag = 0;
    tio.c_oflag = 0;
    tio.c_cflag = CS8|CREAD|CLOCAL; // 8n1
    tio.c_lflag = 0;
    tio.c_cc[VMIN] = 0;
    tio.c_cc[VTIME] = (serial_timeout*10);

    ttyS1_fd = open(USART_DEV_DATA, O_RDWR | O_NONBLOCK);
    if(ttyS1_fd == -1)
    	return EXIT_FAILURE;
    cfsetospeed(&tio, aux_CFG_GetBaudRate(SERIAL_DATA));
    cfsetispeed(&tio, aux_CFG_GetBaudRate(SERIAL_DATA));
    tcsetattr(ttyS1_fd,TCSANOW,&tio);
    tcflush(ttyS1_fd, TCIOFLUSH);
	#endif

    return EXIT_SUCCESS;
}

/**
  * @brief  Envia um buffer, inclusive '\0'.
  * @param  char *s, buffer
  * @param  int len, tamanho do buffer
  * @retval Nenhum
  */
void aux_USART0_putc(const char *s, int len)
{
	int nenv = 0;
	int n = 0;

	do
	{
		do
		{
			nenv = write(ttyS0_fd, s+n, len-n);
			if(nenv <= 0) usleep(SYS_DELAY);
		}while(nenv <= 0);
		n += nenv;
	}while(n < len);
}

/**
  * @brief  Envia string, termina no '\0'.
  * @param  char *format, ...: Formato e variáveis
  * @retval Nenhum
  */
int aux_USART0_puts(const char *format, ...)
{
	int nenv = 0;
	int n = 0;
	int len = 0;
	char buf[USART_TX_LEN];
	va_list args;

	bzero(buf, sizeof(buf));

	va_start(args, format);
	vsprintf(buf, format, args);
	va_end(args);

	len = strlen(buf);

	do
	{
		do
		{
			nenv = write(ttyS0_fd, buf+n, len-n);
			if(nenv <= 0) usleep(SYS_DELAY);
		}while(nenv <= 0);
		n += nenv;
	}while(n < len);

	return len;
}

/**
  * @brief  Envia um buffer, inclusive '\0'.
  * @param  char *s, buffer
  * @param  int len, tamanho do buffer
  * @retval Nenhum
  */
void aux_USART1_putc(const char *s, int len)
{
	int nenv = 0;
	int n = 0;

	do
	{
		do
		{
			nenv = write(ttyS1_fd, s+n, len-n);
			if(nenv <= 0) usleep(SYS_DELAY);
		}while(nenv <= 0);
		n += nenv;
	}while(n < len);
}

/**
  * @brief  Envia string, termina no '\0'.
  * @param  char *format, ...: Formato e variáveis
  * @retval Nenhum
  */
int aux_USART1_puts(const char *format, ...)
{
	int nenv = 0;
	int n = 0;
	int len = 0;
	char buf[USART_TX_LEN];
	va_list args;

	bzero(buf, sizeof(buf));

	va_start(args, format);
	vsprintf(buf, format, args);
	va_end(args);

	len = strlen(buf);

	do
	{
		do
		{
			nenv = write(ttyS1_fd, buf+n, len-n);
			if(nenv <= 0) usleep(SYS_DELAY);
		}while(nenv <= 0);
		n += nenv;
	}while(n < len);

	return len;
}

/**
  * @brief  Lê dados da serial, termina no '\n' ou '\r' exclusivo.
  * @param  char *s: Ponteiro para string de retorno
  * @retval int: Número de bytes lidos
  */
int aux_USART0_gets(char *s)
{
	char buf[USART_RX_LEN];
	int i = 0;
	int nrec = 0;
	int cont = 0;
	BooleanType_t sai = FALSE;

	serial0_timeout = 0;
	bzero(buf, sizeof(buf));

	do
	{
		nrec = read(ttyS0_fd, buf, USART_RX_LEN);

		if(nrec <= 0) usleep(SYS_DELAY);

		if(nrec > 0)
		{
			serial0_timeout = 0;

			for(i=0;i<nrec;i++)
			{
				if((buf[i] != '\r') && (buf[i] != '\n') && (cont < USART_RX_LEN))
				{
					((char *)s)[cont] = buf[i];
					cont++;
				}
				else
				{
					sai = TRUE;
				}
			}
		}
	}while((sai == FALSE) && (serial0_timeout < serial_timeout));

	return cont;
}

/**
  * @brief  Lê dados da serial, termina por timeout ou pelo
  *         numero de bytes lidos.
  * @param  char *s: Ponteiro para string de retorno
  * @retval int: Número de bytes lidos
  */
int aux_USART1_gets(char *s, int len)
{
	int nrec = 0;
	int cont = 0;

	serial1_timeout = 0;

	do
	{
		nrec = read(ttyS1_fd, s+cont, len-cont);

		if(nrec <= 0) usleep(SYS_DELAY);

		if(nrec > 0)
		{
			serial1_timeout = 0;
			cont += nrec;
		}
	}while((cont < len) && (serial1_timeout < serial_timeout) && (cont < USART_RX_LEN));

	//tcflush(ttyS1_fd, TCIOFLUSH);

	return cont;
}

/**
  * @}
  */

/**
  * @}
  */





